package es.ceura.wilder.parsers;

import es.ceura.wilder.actions.Actions;
import es.ceura.wilder.actions.UnsuportedActionException;
import es.ceura.wilder.datastructures.request.HTTPRequest;
import es.ceura.wilder.datastructures.Header;
import es.ceura.wilder.datastructures.HeaderType;
import es.ceura.wilder.datastructures.Message;
import es.ceura.wilder.datastructures.Headers;
import es.ceura.wilder.datastructures.request.StatusLine;
import es.ceura.wilder.logger.Logger;
import java.util.HashMap;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * @author Jorge Madrid
 */
public class HTTPRequestParser {

    private Message message;
    private String messageString;
    private static final String STATUS_REGEX = "([^ ]+)[ ]+([^ ]+)[ ]+([^ ]+)";
    private static final String HEADER_REGEX = "([^ ]+)[ ]*:[ ]*(.*)";
    private Pattern p;
    private Matcher m;
    private Scanner scanner;

    public HTTPRequestParser() {
    }

    public HTTPRequest parseHTTPRequest(String message)
            throws UnsuportedActionException, InvalidHTTPRequestException {

        scanner = new Scanner(message);
        HTTPRequest request;
        HashMap<HeaderType, Header> headerMap;

        final StatusLine statusLine = parseStatusLine(getNewLine());
        headerMap = parseHeaders();

        request = new HTTPRequest(statusLine, headerMap, "");

        return request;
    }

    private StatusLine parseStatusLine(String statusLine)
            throws UnsuportedActionException, InvalidHTTPRequestException {
        p = Pattern.compile(STATUS_REGEX);
        m = p.matcher(statusLine);

        if (m.matches()) {
            final String method = m.group(1);
            final String resourcePath = m.group(2);
            final String httpVersion = m.group(3);

            return new StatusLine(Actions.INSTANCE.getAction(method),
                    resourcePath, httpVersion);
        } else {
            throw new InvalidHTTPRequestException("Error while trying to "
                    + "parse HTTP status line: " + statusLine);
        }
    }

    private HashMap<HeaderType, Header> parseHeaders() {
        String headerLine;
        HashMap<HeaderType, Header> headerMap = new HashMap<>();
        while (!"".equals(headerLine = getNewLine())) {
            p = Pattern.compile(HEADER_REGEX);
            m = p.matcher(headerLine);
            if (m.matches()) {
                final String key = m.group(1);
                final String value = m.group(2);

                HeaderType headerType = Headers.INSTANCE.getHeader(key);
                headerMap.put(headerType, new Header(value));

            } else {
                Logger.INSTANCE.logError("Invalid Header: " + headerLine);
            }
        }
        return headerMap;
    }

    private String getNewLine() {
        if (scanner.hasNextLine()) {
            return scanner.nextLine();
        }
        return "";
    }
}
